import Cookies from "js-cookie"
import CryptoJS from 'crypto-js'
import {DEFAULT_DATA_SECRET_KEY} from "@/common/comConstant/commoncanstant.ts";

/**
 * 策略枚举
 */
export enum StorageStrategy {
    COOKIE_STORAGE = "cookieStorage",
    SESSION_STORAGE = "sessionStorage",
    LOCAL_STORAGE = "localStorage",
}

/**
 * 统一存储接口
 */
export interface StorageInterface {
    set(key: string, value: any): void

    setWithExpiration(key: string, value: any, expiration: number): void

    get(key: string): any

    remove(key: string): void

    clear(): void
}

export abstract class EncoderAbstract {

    key: string = DEFAULT_DATA_SECRET_KEY

    abstract encode(value: string): string

    abstract unencode(value: string): string
}

export class CookiesStorageFactory implements StorageInterface {
    set(key: string, value: string) {
        Cookies.set(key, value)
    }

    setWithExpiration(key: string, value: string, expiration: number) {
        const expires = new Date()
        expires.setTime(expires.getTime() + expiration)
        // expires:默认单位是天  也可以指定到期时间
        Cookies.set(key, value, {
            expires: expires
        })
    }

    get(key: string) {
        return Cookies.get(key)
    }

    remove(key: string) {
        Cookies.remove(key)
    }

    clear() {
        for (let cookiesKey in Cookies) {
            Cookies.remove(cookiesKey)
        }
    }

    static instance(): StorageInterface {
        return new CookiesStorageFactory()
    }
}

export class LocalStorageFactory implements StorageInterface {

    set(key: string, value: string) {
        localStorage.setItem(key, value)
    }

    setWithExpiration(key: string, value: any, expiration: number) {
        throw new Error("不支持时间设定")
    }

    get(key: string): string | null {
        return localStorage.getItem(key)
    }

    remove(key: string) {
        localStorage.removeItem(key)
    }

    clear() {
        localStorage.clear()
    }

    static instance(): StorageInterface {
        return new LocalStorageFactory()
    }
}

export class SessionStorageFactory implements StorageInterface {
    set(key: string, value: string) {
        sessionStorage.setItem(key, value)
    }

    setWithExpiration(key: string, value: any, expiration: number) {
        throw new Error("不支持时间设定")
    }

    get(key: string): string | null {
        return sessionStorage.getItem(key)
    }

    remove(key: string) {
        sessionStorage.removeItem(key)
    }

    clear() {
        sessionStorage.clear()
    }

    static instance(): StorageInterface {
        return new SessionStorageFactory()
    }
}

export class StorageUtil extends EncoderAbstract implements StorageInterface {

    strategy: StorageStrategy = StorageStrategy.SESSION_STORAGE
    openSecret: boolean = true //开启加密
    buildKey(key: string) {
        this.key = key
        return this
    }

    buildOpenSecret(openSecret: boolean) {
        this.openSecret = openSecret
        return this
    }

    buildStrategy(strategy: StorageStrategy) {
        this.strategy = strategy
        return this
    }

    getInstance(): StorageInterface {
        if (this.strategy == StorageStrategy.COOKIE_STORAGE) {
            return CookiesStorageFactory.instance()
        } else if (this.strategy == StorageStrategy.SESSION_STORAGE) {
            return SessionStorageFactory.instance()
        } else if (this.strategy == StorageStrategy.LOCAL_STORAGE) {
            return LocalStorageFactory.instance()
        } else {
            return SessionStorageFactory.instance()
        }
    }

    setKey(key: string) {
        this.key = key
    }

    encode(value: string): string {
        if (!value) return '';
        // 使用默认的 CBC 模式 + Pkcs7 填充，自动加 salt
        return CryptoJS.AES.encrypt(value, this.key).toString(); // 自动输出 Base64 字符串
    }


    /**
     * 解密字符串
     */
    unencode(value: string): string {
        if (!value) {
            console.warn('解密空值');
            return '';
        }
        try {
            const bytes = CryptoJS.AES.decrypt(value, this.key);
            return bytes.toString(CryptoJS.enc.Utf8)
        } catch (error) {
            console.error('解密失败:', error);
            return '';
        }
    }

    set(key: string, value: string) {

        if (this.openSecret) {
            value = this.encode(value)
        }
        this.getInstance().set(key, value)
    }

    setWithExpiration(key: string, value: any, expiration: number) {
        if (this.openSecret) {
            value = this.encode(value)
        }
        this.getInstance().setWithExpiration(key, value, expiration)
    }

    get(key: string) {
        const value = this.getInstance().get(key)
        if (this.openSecret) {
            return this.unencode(value)
        }
        return value
    }

    remove(key: string) {
        this.getInstance().remove(key)
    }

    clear() {
        this.getInstance().clear()
    }
}
